import 'package:flutter/material.dart';

///单一状态样式的组件状态属性，状态属性的定义考虑了不同维度(WidgetState)的状态交叠形成的样式，
///但一般我们的使用场景可能只考虑其中一种状态的是与否下的样式，所以延申此子类用于快速实现需求。
///扩展多状态但不交叠判断，我们需要为不同维度的状态分配优先级，这会增加使用负担，所以这里固定了优
///先级，参考构造方法声明的参数顺序，越前面的优先级越高
class WidgetStatePropertySingle<T> extends WidgetStateProperty<T?> {
  /// 禁用状态，一般我们认为禁用状态下的组件其它状态没有意义，所以是最高优先级
  T? disabled;

  /// 错误状态，部分组件支持状态设置error类型，堪比禁用，这里作为次优先级
  T? error;

  ///我们按照操作流程来看，鼠标悬停到组件上方，按下，再拖拽，后者事件发生时大概率前者已经发生，所
  ///以我们将后者优先级提高以避免一直显示前一步的状态。
  /// 拖拽中
  T? dragged;

  /// 按下，一般用于体现点击交互，时间很短，可以优先覆盖其它事件
  T? pressed;

  /// 鼠标悬停
  T? hovered;

  /// 取得焦点，重要性高于选中，用户在操作焦点时，可能会在一系列已经选中的组件中切换焦点
  T? focused;

  /// 选中
  T? selected;

  /// 滚动到重叠部位（例如Material3 AppBar在内容滚动到它底部时颜色从background切换成
  /// surfaceContainer），这个应该基本用不到。
  T? scrolledUnder;

  /// 其它状态，推荐设置但并非一定要设置，因为很多组件在通过状态属性获取不到对应样式时，会有其它
  /// 其它方案，例如通过主题配置的状态属性或者样式。
  T? other;

  /// 次级方案提供者
  /// 可以传入另一个状态属性的resolve方法对象，我们将其作为备选方案来查询属性。
  /// 使用场景很少，一般是用于像icon需要与某个组件同步样式但又有些许差异，可以通过此类将其状态属
  /// 性的resolve方法对象传入实现部分状态样式的替代，并用resolve查询其当前状态下应该使用的样式
  WidgetPropertyResolver<T?>? secondaryResolver;

  WidgetStatePropertySingle({
    this.disabled,
    this.error,
    this.dragged,
    this.pressed,
    this.hovered,
    this.focused,
    this.selected,
    this.scrolledUnder,
    this.other,
    this.secondaryResolver,
  });

  @override
  T? resolve(Set<WidgetState> states) {
    if (disabled != null && states.contains(WidgetState.disabled)) {
      return disabled;
    }
    if (error != null && states.contains(WidgetState.error)) {
      return error;
    }
    if (dragged != null && states.contains(WidgetState.dragged)) {
      return dragged;
    }
    if (pressed != null && states.contains(WidgetState.pressed)) {
      return pressed;
    }
    if (hovered != null && states.contains(WidgetState.hovered)) {
      return hovered;
    }
    if (focused != null && states.contains(WidgetState.focused)) {
      return focused;
    }
    if (selected != null && states.contains(WidgetState.selected)) {
      return selected;
    }
    if (scrolledUnder != null && states.contains(WidgetState.scrolledUnder)) {
      return scrolledUnder;
    }
    if (other != null) {
      return other;
    }
    return secondaryResolver?.call(states);
  }
}

// ignore: unused_element
void _example() {
  final srcState = {WidgetState.selected, WidgetState.focused};
  final src = WidgetStateColor.resolveWith((s) => Colors.red);
  final replaced = WidgetStatePropertySingle<Color?>(
    focused: Colors.green,
    secondaryResolver: src.resolve,
  );
  // ignore: unused_local_variable
  final style = replaced.resolve(srcState);
}
